class Promise {
  // 回调收集
  callbacks = [];
  // 返回值保存
  value = null;
  // 错误原因
  reason = null;
  // 状态管理
  state = "pending";
  constructor(fn) {
    this._initBind();
    // 传递resolve、和reject方法
    try {
      fn(this._resolve, this._reject);
    } catch (error) {
      this._reject(error);
    }
  }
  _initBind() {
    // 绑定 this
    // 因为 resolve 和 reject 会在 exector 作用域中执行，因此这里需要将 this 绑定到当前的实例
    this._resolve = this._resolve.bind(this);
    this._reject = this._reject.bind(this);
  }

  then(onFulfilled = null, onRejected = null) {
    const me = this;
    // 可以使得promise值穿透
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };
    let p;
    return (p = new Promise(function (resolve, reject) {
      setTimeout(() => {
        // 将收集的回调封装成对象
        try {
          me._handle({
            onFulfilled,
            onRejected,
            resolve,
            reject,
            p,
          });
        } catch (error) {
          reject(error);
        }
      });
    }));
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(done) {
    const p = this.constructor;
    return this.then(
      /**
       *  测试案例:
       * new Promise((resolve) => resolve(123)).finally(val => {console.log(val); return 456;}).then(v => console.log(v))
       * 输出：
       * undefined
       * 123
       * TODO: 所以这里注意finally.then的值是调用finally的promise的value值
       */
      (val) => p.resolve(done()).then(() => val),
      (reason) =>
        p.resolve(done()).then(() => {
          throw reason;
        })
    );
  }

  _handle(cbObj) {
    const me = this;
    // 首先判断状态
    if (me.state === "pending") {
      me.callbacks.push(cbObj);
      return;
    }
    // 依据状态获取用户回调
    const cb = me.state === "fulfilled" ? cbObj.onFulfilled : cbObj.onRejected;
    // 异常处理
    try {
      const val = cb(me.state === "fulfilled" ? me.value : me.reason);
      // 根据回调的返回值，来决定内置promise的状态
      Promise._pResolve(cbObj, val, cbObj.p);
    } catch (error) {
      cbObj.reject(error);
    }
  }

  _resolve(val) {
    const me = this;
    const doResolve = (value) => {
      me.value = value
      me.state = 'fulfilled'
      me._execute()
    }
    if (me.state === "pending") {
      // 补充逻辑
      if(val instanceof Promise) {
        if(val.state !== 'pending') {
          val = val.value || val.reason
        } else {
          val.then(v => {
            if(me.state === 'pending') {
              doResolve(v)
            }
          }, r => {
            
          })
        }
      }
      setTimeout(() => {
        doResolve(val)
      });
    }
  }
  _reject(reason) {
    const me = this;
    if (me.state === "pending") {
      setTimeout(() => {
        me.reason = reason;
        me.state = "rejected";
        me._execute();
      });
    }
  }
  _execute() {
    const me = this;
    me.callbacks.forEach(function (cbObj) {
      me._handle(cbObj);
    });
  }
}

Promise._pResolve = (obj, val, p) => {
  let called = false;
  if (p === val) {
    obj.reject(
      new TypeError(
        "cannot return the same promise object from onfulfilled or on rejected callback."
      )
    );
    return;
  }
  if (val instanceof Promise) {
    if (val.state === "pending") {
      val.then(
        (v) => {
          Promise._pResolve(obj, v, p);
        },
        (error) => {
          obj.reject(error);
        }
      );
    } else {
      if (val.state === "fulfilled") {
        obj.resolve(val.value);
      } else {
        obj.reject(val.reason);
      }
    }
  } else if (val && (typeof val === "object" || typeof val === "function")) {
    // 判断val是否是promise对象，有没有then方法可以挂载
    try {
      const valThen = val.then;
      if (typeof valThen === "function") {
        // 保持this指向正确，如果不用call，此时then中的this会指向内置promise，而不是用户自己的promise
        valThen.call(
          val,
          (v) => {
            if (called) return;
            called = true;
            return Promise._pResolve(obj, v, p);
          },
          (error) => {
            if (called) return;
            called = true;
            return obj.reject(error);
          }
        );
      } else obj.resolve(val);
    } catch (error) {
      if (called) return;
      called = true;
      return obj.reject(error);
    }
  } else obj.resolve(val);
};

Promise.resolve = function (val) {
  if (val && val instanceof Promise) {
    // 如果参数是promise对象，我们直接返回
    return val;
  } else if (val && (typeof val === "object" || typeof val === "function")) {
    // 如果参数是对象，则判断有没有then方法，并新建个promise对象包裹
    try {
      const valThen = val.then;
      if (valThen && typeof valThen === "function") {
        return new Promise((resolve, reject) => {
          // 由参数then的直接决定promise状态
          valThen.call(val, resolve, reject);
        });
      } else return new Promise((resolve) => resolve(val));
    } catch (error) {
      // 异常处理
      return new Promise((resolve, reject) => reject(error));
    }
  } else if (val !== void 0) {
    // 参数是不是具有then方法的数据，普通参数
    return new Promise((resolve) => resolve(val));
    // 接着就是没有传递参数的情况
  } else return new Promise((resolve) => resolve());
};

Promise.reject = function (val) {
  // 是否是promise对象或者包含then方法的对象
  if (val && (typeof val === "object" || typeof val === "function")) {
    try {
      const valThen = val.then;
      if (valThen && typeof valThen === "function") {
        return new Promise((resolve, reject) => {
          // 只处理reject
          valThen.call(val, null, reject);
        });
      } else return new Promise((resolve, reject) => reject(val));
    } catch (error) {
      return new Promise((resolve, reject) => reject(error));
    }
    // 其他情况直接将val作为错误原因
  } else return new Promise((resolve, reject) => reject(val));
};

Promise.all = function (iterator) {
  let count = 0;
  // 将iterator转化成数组
  const arr = Array.from(iterator);
  const len = arr.length;
  // 结果
  const result = [];
  return new Promise((resolve, reject) => {
    for (let i = 0; i < len; i++) {
      const itemP = arr[i];
      Promise.resolve(itemP)
        .then((res) => {
          count++;
          result[i] = res;
          // 所有promise都返回成功状态，并将返回值保存。最后执行resolve
          if (count === len) {
            resolve(result);
          }
        })
        .catch((err) => {
          // 错误处理
          reject(err);
        });
    }
  });
};

Promise.race = function (iterator) {
  // 将iterator转化成数组
  const arr = Array.from(iterator);
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      const itemP = arr[i];
      Promise.resolve(itemP)
        .then((result) => {
          resolve(result);
        })
        .catch((err) => {
          // 错误处理
          reject(err);
        });
    }
  });
};